print("202501141615 - ReplicatedStorage 全量数据探索器 ")

local HttpService = game:GetService("HttpService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")

local LocalPlayer = Players.LocalPlayer

local function log(msg)
	local line = string.format("[%s] %s", os.date("%Y-%m-%d %H:%M:%S"), tostring(msg))
	print("[RSExplorer] " .. msg)
	local ok = pcall(function()
		appendfile("rs_explorer_log.txt", line .. "\n")
	end)
	if not ok then
		pcall(function()
			writefile("rs_explorer_log.txt", line .. "\n")
		end)
	end
end

-- 安全 tostring
local function safeToString(v)
	local ok, res = pcall(function() return tostring(v) end)
	if ok then return res else return "[unstringifiable]" end
end

-- 摘要一个值
local function summarizeValue(v, depth)
	depth = depth or 0
	if depth > 2 then return { kind = typeof(v) } end
	local t = typeof(v)
	if t ~= "table" then
		return { kind = t, value = (t == "string" and v) or safeToString(v) }
	end
	-- 表：采样少量键，防止爆量
	local out = { kind = "table", sample = {} }
	local count = 0
	for k, val in pairs(v) do
		count = count + 1
		if count <= 10 then
			out.sample[safeToString(k)] = summarizeValue(val, depth + 1)
		else
			break
		end
	end
	out.sampleCount = count
	return out
end

-- 安全 require 模块
local function safeRequire(mod)
	local ok, res = pcall(function()
		return require(mod)
	end)
	if not ok then
		return false, safeToString(res)
	end
	return true, res
end

-- 主逻辑：遍历 ReplicatedStorage
local function exploreReplicatedStorage()
	log("🚀 开始遍历 ReplicatedStorage...")
	-- 配置：是否尝试 require 模块（默认关闭，避免卡住）
	local shouldRequireModules = false

	-- 预先统计后续遍历规模
	local preDesc = {}
	pcall(function()
		preDesc = ReplicatedStorage:GetDescendants()
	end)
	log("📦 预检: GetDescendants 数量 = " .. tostring(#preDesc))
	local summary = {
		metadata = {
			exportTime = os.date("%Y-%m-%d %H:%M:%S"),
			player = LocalPlayer and LocalPlayer.Name or "?",
			version = "1.0"
		},
		instances = {},
		modules = {},
		stats = {
			total = 0,
			folders = 0,
			modules = 0,
			others = 0
		}
	}

	local processed = 0
	local batch = 0
	local descendants = preDesc
	if #descendants == 0 then
		-- 回退：仅遍历一级子对象，便于快速验证
		log("ℹ️ GetDescendants 为空，回退到 GetChildren() 进行遍历")
		pcall(function()
			descendants = ReplicatedStorage:GetChildren()
		end)
	end

	for _, inst in ipairs(descendants) do
		processed = processed + 1
		batch = batch + 1
		summary.stats.total = summary.stats.total + 1
		local className = inst.ClassName
		local entry = {
			name = inst.Name,
			className = className,
			path = inst:GetFullName(),
		}
		if className == "Folder" then
			summary.stats.folders = summary.stats.folders + 1
		elseif className == "ModuleScript" then
			summary.stats.modules = summary.stats.modules + 1
			if shouldRequireModules then
				local ok, res = safeRequire(inst)
				if ok then
					entry.requireOk = true
					entry.summary = summarizeValue(res)
				else
					entry.requireOk = false
					entry.error = res
				end
			end
			table.insert(summary.modules, entry)
		else
			summary.stats.others = summary.stats.others + 1
		end
		table.insert(summary.instances, entry)

		-- 每处理一定数量输出一次进度，避免长时间没有日志
		if (processed % 200) == 0 then
			log("⏳ 进度: 已处理 " .. processed .. " / " .. tostring(#descendants))
		end
		-- 主线程让步，防止界面卡死
		if batch >= 400 then
			batch = 0
			task.wait()
		end
	end

	-- 导出 JSON
	local okJson, encoded = pcall(function()
		return HttpService:JSONEncode(summary)
	end)
	if okJson then
		pcall(function()
			writefile("rs_explorer_data.json", encoded)
			log("✅ 已导出 rs_explorer_data.json")
		end)
	end

	-- 导出文本
	local lines = {}
	table.insert(lines, "=== ReplicatedStorage 全量数据探索 ===")
	table.insert(lines, "导出时间: " .. summary.metadata.exportTime)
	table.insert(lines, "玩家: " .. summary.metadata.player)
	table.insert(lines, "总实例: " .. summary.stats.total)
	table.insert(lines, "Folder: " .. summary.stats.folders)
	table.insert(lines, "ModuleScript: " .. summary.stats.modules)
	table.insert(lines, "其他: " .. summary.stats.others)
	table.insert(lines, "")
	table.insert(lines, "=== 模块摘要(前50) ===")
	for i = 1, math.min(50, #summary.modules) do
		local m = summary.modules[i]
		table.insert(lines, string.format("%d. %s (%s)", i, m.name, m.path))
		table.insert(lines, "   requireOk: " .. tostring(m.requireOk))
		if m.requireOk and m.summary then
			table.insert(lines, "   kind: " .. tostring(m.summary.kind))
			if m.summary.kind == "table" then
				table.insert(lines, "   sampleCount: " .. tostring(m.summary.sampleCount))
			end
		elseif m.error then
			table.insert(lines, "   error: " .. m.error)
		end
	end

	pcall(function()
		writefile("rs_explorer_data.txt", table.concat(lines, "\n"))
		log("✅ 已导出 rs_explorer_data.txt")
	end)

	log("📊 遍历完成，总实例: " .. summary.stats.total .. ", 模块: " .. summary.stats.modules)
	return true
end

-- UI
local function createUI()
	local screenGui = Instance.new("ScreenGui")
	screenGui.Name = "ReplicatedStorageExplorer"
	screenGui.ResetOnSpawn = false
	screenGui.Parent = game.CoreGui

	local main = Instance.new("Frame")
	main.Name = "Main"
	main.Size = UDim2.new(0, 420, 0, 160)
	main.Position = UDim2.new(0, 10, 0, 10)
	main.BackgroundColor3 = Color3.fromRGB(30,30,30)
	main.BorderSizePixel = 1
	main.BorderColor3 = Color3.fromRGB(100,100,100)
	main.Parent = screenGui

	local title = Instance.new("TextLabel")
	title.Size = UDim2.new(1, 0, 0, 32)
	title.Text = "ReplicatedStorage 全量数据探索器"
	title.TextColor3 = Color3.new(1,1,1)
	title.BackgroundTransparency = 1
	title.TextScaled = true
	title.Font = Enum.Font.SourceSansBold
	title.Parent = main

	local runBtn = Instance.new("TextButton")
	runBtn.Size = UDim2.new(0, 180, 0, 36)
	runBtn.Position = UDim2.new(0, 20, 0, 50)
	runBtn.Text = "开始遍历 (R)"
	runBtn.TextScaled = true
	runBtn.TextColor3 = Color3.new(1,1,1)
	runBtn.BackgroundColor3 = Color3.fromRGB(70, 130, 70)
	runBtn.BorderSizePixel = 0
	runBtn.Parent = main
	runBtn.MouseButton1Click:Connect(function()
		exploreReplicatedStorage()
	end)

	local status = Instance.new("TextLabel")
	status.Size = UDim2.new(1, -20, 0, 50)
	status.Position = UDim2.new(0, 10, 0, 95)
	status.Text = "按R开始遍历并导出JSON/文本\n结果文件: rs_explorer_data.json / rs_explorer_data.txt"
	status.TextWrapped = true
	status.TextColor3 = Color3.fromRGB(200,200,200)
	status.BackgroundTransparency = 1
	status.TextScaled = true
	status.Font = Enum.Font.SourceSans
	status.Parent = main

	return screenGui
end

-- 快捷键
local UserInputService = game:GetService("UserInputService")
UserInputService.InputBegan:Connect(function(input, gp)
	if gp then return end
	if input.KeyCode == Enum.KeyCode.R then
		exploreReplicatedStorage()
	end
end)

log("ReplicatedStorage 全量数据探索器已加载")
createUI()
